﻿#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

//宏和函数的对比
//宏有时候可以做函数做不到的事情。⽐如：宏的参数可以出现类型，但是函数做不到

//#define MALLOC(num,type) (type*)malloc(num*sizeof(type))
//int main()
//{
//	int* p1 = (int*)malloc(10 * sizeof(int));
//	int* p2 = MALLOC(10, int);
//	//int* p2 = (int*)malloc(10*sizeof(int));
//	return 0;
//}

// #undef
//这条指令用于移除一个宏定义
//#undef NAME
//如果现存的⼀个名字需要被重新定义，那么它的旧名字⾸先要被移除。 

//#define MAX 100
//int main()
//{
//	printf("%d\n", MAX);
//#undef MAX
//	printf("%d\n", MAX);
//	return 0;
//}

//条件编译
//在编译一个程序的时候我们如果要将一条语句（一组语句）编译或者放弃是很方便的。因为我们有条件编译指令。
//⽐如说：
//调试性的代码，删除可惜，保留⼜碍事，所以我们可以选择性的编译。

//#define PRINT 0
//int main()
//{
//#ifdef PRINT
//	printf("hehe\n");
//#endif
//	return 0;
//}

//常见的条件编译指令
//int main()
//{
//#if 1
//	printf("haha\n");
//#endif
//	return 0;
//}
//1.常量表达式由预处理器求值
//#define M 1
//int main()
//{
//#if M
//	printf("haha\n");
//#endif
//	return 0;
//}

//2.多个分支的条件编译
//#define M 4
//int main()
//{
//#if M==1
//	printg("hehe\n");
//#elif M==5
//	printf("haha\n");
//#else
//	printf("heihei\n");
//#endif
//	return 0;
//}

//3.判断是否被定义
//#define MAX 0
//int main()
//{
////#if defined(MAX)
//#ifdef MAX
//	printf("hehe\n");
//#endif
//	return 0;
//}

//#define MAX 10
//int main()
//{
////#if !defined(MAX)
//#ifndef MAX
//	printf("hehe\n");
//#endif
//	return 0;
//}

//4.嵌套指令
//#define S1 2
////#define P1 5
////#define S2 4
//#define P2 3
//int main()
//{
//#if defined(S1)
//	#ifdef P1
//		printf("hehe\n");
//	#endif
//	#ifdef P2
//		printf("haha\n");
//	#endif
//#elif defined(S2)
//	#ifdef P2
//		printf("heihei\n");
//	#endif
//#endif
//	return 0;
//}

//头文件的包含

//#include "test.h"
//int main()
//{
//
//	return 0;
//}

//其他的预处理指令
//1.#error
//作用：强制中断编译过程，并输出自定义错误消息。
//语法：#error "错误消息"
//典型用途：
//检查不满足的编译条件（如依赖的宏未定义）
//防止使用不兼容的编译器或环境
//提示开发者修复配置问题

//int main()
//{
//#if !defined(__cplusplus)
//#error "本代码必须使用C++编译器！"     
//#endif
//	return 0;
//}//如果使用C编译器（而非C++），编译将中断并显示错误消息。

//2.#pragma
//作用：向编译器传递特定指令（编译器相关，非C/C++标准强制要求）。
//语法：#pragma 指令内容
//典型用途：
//控制内存对齐（#pragma pack）
//禁用编译器警告（#pragma warning(disable: xxx)）
//确保头文件只包含一次（#pragma once）
//其他编译器优化或特殊功能

//int main()
//{
//#pragma pack(1)          // 设置1字节对齐（取消填充）
//	struct Data 
//	{
//		char a;              // 1字节
//		int b;               // 4字节（无填充）
//	};                       // 结构体总大小=5字节
//#pragma pack()           // 恢复默认对齐
//
//#pragma once             // 确保头文件仅被包含一次（跨编译器支持）
//	return 0;
//}

//3.#line
//作用：修改编译器报告的行号和文件名（常用于代码生成工具）。
//语法：#line 行号 "文件名"
//典型用途：
//当代码由工具自动生成时（如Lex / Yacc），使错误信息指向原始源文件位置
//调试时自定义错误定位

int main()
{
	int y = 10;
#line 180 "test.c"  // 下一行代码的行号设为100，文件名设为"my_source.txt"
	int x = y / 0;             // 若此处出错，编译器报错位置：my_source.txt:101
	return 0;
}